package me.gavin.base

import android.os.Bundle
import androidx.fragment.app.Fragment

/**
 * PerceptibleFragment - 生命周期易感知
 * onActivityCreated() -> onLazyInitView() -> onSupportVisible -> onSupportInvisible()
 *
 * @author gavin.xiong 2018/3/28
 */
abstract class PerceptibleFragment : Fragment() {

    private var flag = FLAG_NONE

    private var savedInstanceState: Bundle? = null

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        this.savedInstanceState = savedInstanceState
        addFlag(FLAG_IS_CREATED)
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        addFlag(FLAG_IS_IN_VP)
        if (isVisibleToUser) {
            addFlag(FLAG_IS_VISIBLE_TO_USER)
        } else {
            removeFlag(FLAG_IS_VISIBLE_TO_USER)
        }
        if (containFlag(FLAG_IS_CREATED)) {
            if (isVisibleToUser) {
                isSupportVisible = true
            } else if (containFlag(FLAG_IS_INITIALIZED)) {
                isSupportVisible = false
            }
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (!hidden) {
            isSupportVisible = true
        } else if (containFlag(FLAG_IS_INITIALIZED)) {
            isSupportVisible = false
        }
    }

    override fun onResume() {
        super.onResume()
        if (
            containFlag(FLAG_IS_IN_VP) && containFlag(FLAG_IS_VISIBLE_TO_USER) && !isSupportVisible
            || !containFlag(FLAG_IS_IN_VP) && !isHidden && !isSupportVisible
        ) {
            isSupportVisible = true
        }
    }

    override fun onPause() {
        super.onPause()
        if (isSupportVisible) {
            isSupportVisible = false
        }
    }

    private fun addFlag(flag: Int) {
        this.flag = this.flag or flag
    }

    private fun removeFlag(flag: Int) {
        this.flag = this.flag and flag.inv()
    }

    private fun containFlag(flag: Int) = this.flag contain flag

    open fun onLazyInitView(savedInstanceState: Bundle?) {}

    open fun onSupportVisible() {}

    open fun onSupportInvisible() {}

    val isInitialized get() = containFlag(FLAG_IS_INITIALIZED)

    var isSupportVisible: Boolean = false
        private set(value) {
            if (value) {
                if (!isParentVisible) {
                    addFlag(FLAG_IS_PARENT_INVISIBLE)
                    field = false
                } else {
                    field = true
                    if (!containFlag(FLAG_IS_INITIALIZED)) {
                        addFlag(FLAG_IS_INITIALIZED)
                        onLazyInitView(savedInstanceState)
                    }
                    onSupportVisible()
                    childFragmentManager.fragments.forEach {
                        if (it is PerceptibleFragment) {
                            if (it.containFlag(FLAG_IS_PARENT_INVISIBLE)) {
                                it.removeFlag(FLAG_IS_PARENT_INVISIBLE)
                                it.isSupportVisible = true
                            }
                        }
                    }
                }
            } else {
                if (!isParentVisible) {
                    removeFlag(FLAG_IS_PARENT_INVISIBLE)
                    field = false
                } else {
                    childFragmentManager.fragments.forEach {
                        if (it is PerceptibleFragment) {
                            if (it.isSupportVisible) {
                                it.addFlag(FLAG_IS_PARENT_INVISIBLE)
                                it.isSupportVisible = false
                            }
                        }
                    }
                    field = value
                    onSupportInvisible()
                }


            }
        }

    private val isParentVisible get() = (parentFragment as? PerceptibleFragment)?.isSupportVisible != false

    companion object {
        private const val FLAG_NONE = 0
        private const val FLAG_IS_IN_VP = 1 shl 0               // 在 viewPage 中
        private const val FLAG_IS_VISIBLE_TO_USER = 1 shl 1     // 在 viewPage 中 isVisibleToUser
        private const val FLAG_IS_CREATED = 1 shl 2             // onActivityCreated 后
        private const val FLAG_IS_INITIALIZED = 1 shl 3         // 已经加载数据
        private const val FLAG_IS_PARENT_INVISIBLE = 1 shl 4    // 因父容器不可见导致不可见
    }

}